package com.zhuangjie.mvc.helper.GeoHelper;

import java.util.Collection;
import java.util.List;

/**
 * 地理坐标实用程序
 *
 * @author zhuangjie
 * @date 2024/01/21
 */
public class GeoCoordinateUtils {
    private static final int EARTH_RADIUS_KM = 6371;


    /**
     * 获取中心点
     *
     * @param coordinates 协调
     * @return {@link Coordinate}
     */
    public static Coordinate getCenterPoint(List<Coordinate> coordinates) {
        if (coordinates == null || coordinates.isEmpty()) {
            return null;
        }

        double latitude = 0.0;
        double longitude = 0.0;

        for (Coordinate coord : coordinates) {
            latitude += Math.toRadians(coord.latitude);
            longitude += Math.toRadians(coord.longitude);
        }

        int numOfPoints = coordinates.size();
        return new Coordinate(Math.toDegrees(latitude / numOfPoints), Math.toDegrees(longitude / numOfPoints));
    }


    /**
     * 计算地球上两点间的距离。
     *
     * @param lon1 第一个点的经度
     * @param lat1 第一个点的纬度
     * @param lon2 第二个点的经度
     * @param lat2 第二个点的纬度
     * @return 两点间的距离，单位是公里
     */
    public static double calculateDistance(Double lon1, Double lat1, Double lon2, Double lat2) {
        if (lon1 == null || lat1 == null || lon2 == null || lat2 == null) {
            throw new IllegalArgumentException("运算的信息为空，无法计算两点的距离！");
        }
        // 使用Haversine公式来计算
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);

        // 下面是将Haversine公式展开计算
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);

        // 通过a计算c
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        // 乘以地球的半径并返回结果
        return EARTH_RADIUS_KM * c;
    }


    /**
     * 查找最近
     *
     * @param geoCoordinates 地理坐标
     * @param filterPoints   过滤点
     * @return {@link GeoCoordinates}
     */
    public static <T extends GeoCoordinates> T findRecent(GeoCoordinates geoCoordinates, Collection<? extends GeoCoordinates> ...filterPoints) {
        if (geoCoordinates == null ) throw new RuntimeException("起点位置为空！");
        T globalRecentGeoCoordinates = null;
        // 全局的
        double globalMinimumDistance = Double.MAX_VALUE;
        for (Collection<T> filterPoint : (Collection<T>[])filterPoints) {
            // 局部的
            double minimumDistance = Double.MAX_VALUE;
            T recentGeoCoordinates = null;
            for (T point : filterPoint) {
                double distance = calculateDistance(geoCoordinates.getLongitude(), geoCoordinates.getLatitude(),point.getLongitude(), point.getLatitude());
                if (distance < minimumDistance) {
                    minimumDistance = distance;
                    recentGeoCoordinates = point;
                }
            }
            if (minimumDistance < globalMinimumDistance) {
                globalMinimumDistance = minimumDistance;
                globalRecentGeoCoordinates = recentGeoCoordinates;
            }
        }
        return globalRecentGeoCoordinates;
    }






//    public static void main(String[] args) {
//        // 示例坐标点列表
//        List<Coordinate> coordinates = new ArrayList<>();
//        coordinates.add(new Coordinate(116.381128,39.905859));
//        coordinates.add(new Coordinate(116.391189,39.906523));
//        coordinates.add(new Coordinate(116.386123,39.902496));
//
//        // 获取坐标点的中心
//        Coordinate center = getCenterPoint(coordinates);
//        if (center != null) {
//            System.out.println("中心点的纬度: " + center.latitude + ", 经度: " + center.longitude);
//        } else {
//            System.out.println("坐标列表为空");
//        }
//    }
        }